/* globals _ */

define(function () {

    "use strict";

    var exports = {},
		performAjaxCall;

    $.ajaxSetup({ cache: false });

    var $successMessage = $('#SuccessMessage'),
        $failureMessage = $('#FailureMessage'),
        $busyIndicator = $('#BusyIndicator'),
        $ajaxValidationErrors = $('#ajax-validation-errors');

    $.subscribe('successMessage', function (message) {
        if (!message)
            message = 'Operation completed successfully.';
        $successMessage.stop(false, true).text(message).show().delay(3000).fadeOut(3000);
    });

    $.subscribe('failureMessage', function (message) {
        if (!message)
            message = 'Operation failed. Please try again later.';
        $failureMessage.stop(false, true).text(message).show().delay(3000).fadeOut(3000);
    });

    $.subscribe('showBusyIndicator', function () {
        $busyIndicator.show();
    });

    $.subscribe('hideBusyIndicator', function () {
        $busyIndicator.hide();
    });

    $.subscribe('ajaxValidationErrors', function (errors) {
        if (_.isString(errors)) {
            $ajaxValidationErrors.append($('<div>').append(errors));
        } else { // is object
            $.each(errors.validationObjects, function (i, v) {
                var key = v.key;
                var lines = v.lines;
                var keySpan = $('<span>').text(key.charAt(0).toUpperCase() + key.slice(1));
                var valueSpan = $('<span>').text(lines.join(', '));
                var containerDiv = $('<div>').append(keySpan).append('&nbsp;').append(valueSpan);
                $ajaxValidationErrors.append(containerDiv);
            });
        }

        $ajaxValidationErrors.show().delay(3000).fadeOut(5000);
    });

    $.subscribe('clearAjaxValidationErrors', function () {
        $ajaxValidationErrors.empty();
    });

    performAjaxCall = function (url, type, data, options) {

        var settings, deferred;

        settings = _.defaults(options || {}, {
            async: true,
            dataType: 'json',
            showSuccessMessage: true,
            successMessage: 'Operation completed successfully.',
            showFailureMessage: true,
            failureMessage: 'Operation failed. Please try again later.',
            showBusyIndicator: true
        });

        deferred = $.Deferred();

        $.ajax({
            url: '/api/' + url,
            type: type,
            dataType: settings.dataType,
            contentType: "application/json; charset=utf-8",
            async: settings.async,
            data: data,
            beforeSend: function () {
                $.publish('clearAjaxValidationErrors');
                if (!!settings.showBusyIndicator && !!settings.async) $.publish('showBusyIndicator');
            },
            complete: function () {
                $.publish('hideBusyIndicator');
            },
            success: function (response) {
                deferred.resolve(response);
                if (settings.showSuccessMessage)
                    $.publish('successMessage', [settings.successMessage]);
            },
            error: function (xhr, textStatus, error) {
                deferred.reject(xhr, textStatus, error);
                var responseObj = JSON.parse(xhr.responseText);
                switch (xhr.status) {
                    case 303:
                        window.location = responseObj.uri;
                        break;
                    case 406:
                    case 409:
                        $.publish('ajaxValidationErrors', [responseObj]);
                        break;
                    case 500:
                        console.log(responseObj);
                        if (settings.showFailureMessage)
                            $.publish('failureMessage', [settings.failureMessage]);
                        break;
                    default:
                        if (settings.showFailureMessage)
                            $.publish('failureMessage', [settings.failureMessage]);
                        break;
                }
            }
        });

        return deferred.promise();
    };

    _.extend(exports, {
        get: function (url, form, options) {
            options = $.extend({ showSuccessMessage: false }, options || {});
            url += '?' + $.param(form);
            return performAjaxCall(url, 'GET', {}, options);
        },
        post: function (url, form, options) {
            return performAjaxCall(url, 'POST', JSON.stringify(form), options);
        },
        put: function (url, form, options) {
            return performAjaxCall(url, 'PUT', JSON.stringify(form), options);
        },
        del: function (url, id, options) {
            return performAjaxCall(url + "?id=" + id, 'DELETE', null, options);
        },
    });

    return exports;

});

/*

$("#searchForm").validate({
				rules: {
					q: {
						required: true
					}
				},
	            errorPlacement: function(error, element) {

	            },
				highlight: function (element) {
					$(element)
						.closest(".input-group")
						.removeClass("has-success")
						.addClass("has-error");
				},
				success: function (element) {
					$(element)
						.closest(".input-group")
						.removeClass("has-error")
						.addClass("has-success");
				}
			});

            $("#newsletterForm").validate({
				submitHandler: function(form) {

					$.ajax({
						type: "POST",
						url: $("#newsletterForm").attr("action"),
						data: {
							"email": $("#newsletterForm #email").val()
						},
						dataType: "json",
						success: function (data) {
							if (data.response == "success") {

								$("#newsletterSuccess").removeClass("hidden");
								$("#newsletterError").addClass("hidden");

								$("#newsletterForm #email")
									.val("")
									.blur()
									.closest(".control-group")
									.removeClass("success")
									.removeClass("error");

							} else {

								$("#newsletterError").html(data.message);
								$("#newsletterError").removeClass("hidden");
								$("#newsletterSuccess").addClass("hidden");

								$("#newsletterForm #email")
									.blur()
									.closest(".control-group")
									.removeClass("success")
									.addClass("error");

							}
						}
					});

				},
				rules: {
					email: {
						required: true,
						email: true
					}
				},
	            errorPlacement: function(error, element) {

	            },
				highlight: function (element) {
					$(element)
						.closest(".control-group")
						.removeClass("success")
						.addClass("error");
				},
				success: function (element) {
					$(element)
						.closest(".control-group")
						.removeClass("error")
						.addClass("success");
				}
			});


*/